#ifdef _WIN32
#include "DeviceDX9.h"
#include "VertexBufferDX9.h"

using namespace Stray;
using namespace Stray::Core;
using namespace Stray::Core::Graphics;
using namespace Stray::Core::Graphics::DirectX9;

VertexBufferDX9::VertexBufferDX9(IDirect3DVertexBuffer9 *pVertexBuffer, DeviceDX9 *pDevice)
	:LostResource(pDevice)
	,pVertexBuffer_(pVertexBuffer)
{
	pVertexBuffer_->GetDesc(&desc_);
	size_ = desc_.Size;
	pData_ = new Uint8[size_];
}

VertexBufferDX9::~VertexBufferDX9()
{
	if(pVertexBuffer_ != 0) pVertexBuffer_->Release();
	if(pData_) delete [] pData_;
}

void VertexBufferDX9::releaseResource()
{
	if(pVertexBuffer_ != 0) pVertexBuffer_->Release();
}

void VertexBufferDX9::recoverResource()
{
	HRESULT hr = pDevice_->getNativeDevice()->CreateVertexBuffer(
		desc_.Size,
		desc_.Usage,
		desc_.FVF,
		desc_.Pool,
		&pVertexBuffer_,
		0);
	assert(SUCCEEDED(hr));
	if(pData_)
	{
		void *pVB;
		pVertexBuffer_->Lock(0, 0, &pVB, 0);
		memcpy(pVB, pData_, size_);
		pVertexBuffer_->Unlock();
	}
}

size_t VertexBufferDX9::getSize() const
{
	return size_;
}

void* VertexBufferDX9::lock(LockFlag flag)
{
	if(pVertexBuffer_ == 0) return 0;
	void *output;
	DWORD f;
	switch(flag)
	{
	case LF_READWRITE:
		f = 0;
		break;
	case LF_READONLY:
		f = D3DLOCK_READONLY;
		break;
	case LF_DISCARD:
		f = D3DLOCK_DISCARD;
		break;
	case LF_NOOVERWRITE:
		f = D3DLOCK_NOOVERWRITE;
		break;
	}
	pVertexBuffer_->Lock(0, 0, &output, f);
	return output;
}

void VertexBufferDX9::unlock()
{
	if(pVertexBuffer_ == 0) return;
	pVertexBuffer_->Unlock();
	void *pTemp;
	pVertexBuffer_->Lock(0, 0, &pTemp, D3DLOCK_READONLY);
	if(pData_ == 0) pData_ = new Uint8[size_];
	memcpy(pData_, pTemp, size_);
	pVertexBuffer_->Unlock();
}

void VertexBufferDX9::writeData(void* pData, Stray::Uint32 size)
{
	if(pVertexBuffer_ == 0) return;
	Uint32 writeSize = size;
	if(writeSize > size_) writeSize = size_;

	void *pDest = 0;
	pDest = lock();
	memcpy(pDest, pData, writeSize);
	unlock();
}

void VertexBufferDX9::readData(void *pData, Stray::Uint32 *pSize)
{
	*pSize = size_;
	if(pData == 0) return;

	if(pVertexBuffer_ == 0) return;
	void *pSrc = 0;
	pSrc = lock();
	memcpy(pData, pSrc, size_);
	unlock();
}

void* VertexBufferDX9::getNativeHandle() const
{
	return pVertexBuffer_;
}

#endif